package com.hongkuncheng.cms.ueditor.upload;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.annotation.Resource;

import org.apache.commons.io.FileUtils;
import org.hibernate.FactorySession;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Component;
import com.hongkuncheng.cms.model.Watermark;
import com.hongkuncheng.cms.ueditor.define.AppInfo;
import com.hongkuncheng.cms.ueditor.define.BaseState;
import com.hongkuncheng.cms.ueditor.define.State;
import com.hongkuncheng.cms.ueditor.hunter.WaterHunter;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component
public class StorageManager {

    public static final int BUFFER_SIZE = 8192;

    private static WaterHunter waterHunter = new WaterHunter();

    public static State saveBinaryFile(byte[] data, String rootPath, String path, boolean isImage) {
        File file = new File(path);
        State state = valid(file);
        if (!state.isSuccess()) {
            return state;
        }
        try {
            BufferedOutputStream bos = new BufferedOutputStream(
                    new FileOutputStream(file));
            bos.write(data);
            bos.flush();
            bos.close();
        } catch (IOException ioe) {
            return new BaseState(false, AppInfo.IO_ERROR);
        }
        state = new BaseState(true, file.getAbsolutePath());
        state.putInfo("size", data.length);
        state.putInfo("title", file.getName());
        return state;
    }

    public static State saveFileByInputStream(InputStream is, String rootPath, String path,
                                              long maxSize, boolean isImage) {
        State state = null;
        File tmpFile = getTmpFile();
        byte[] dataBuf = new byte[2048];
        BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE);
        try {
            BufferedOutputStream bos = new BufferedOutputStream(
                    new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE);
            int count = 0;
            while ((count = bis.read(dataBuf)) != -1) {
                bos.write(dataBuf, 0, count);
            }
            bos.flush();
            bos.close();
            if (tmpFile.length() > maxSize) {
                tmpFile.delete();
                return new BaseState(false, AppInfo.MAX_SIZE);
            }
            state = saveTmpFile(tmpFile, rootPath, path, isImage);
            if (!state.isSuccess()) {
                tmpFile.delete();
            }
            return state;
        } catch (IOException e) {
        }
        return new BaseState(false, AppInfo.IO_ERROR);
    }

    public static State saveFileByInputStream(InputStream is, String rootPath, String path, boolean isImage) {
        State state = null;
        File tmpFile = getTmpFile();
        byte[] dataBuf = new byte[2048];
        BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE);
        try {
            BufferedOutputStream bos = new BufferedOutputStream(
                    new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE);
            int count = 0;
            while ((count = bis.read(dataBuf)) != -1) {
                bos.write(dataBuf, 0, count);
            }
            bos.flush();
            bos.close();
            state = saveTmpFile(tmpFile, rootPath, path, isImage);
            if (!state.isSuccess()) {
                tmpFile.delete();
            }
            return state;
        } catch (IOException e) {
        }
        return new BaseState(false, AppInfo.IO_ERROR);
    }

    private static File getTmpFile() {
        File tmpDir = FileUtils.getTempDirectory();
        String tmpFileName = (Math.random() * 10000 + "").replace(".", "");
        return new File(tmpDir, tmpFileName);
    }

    private static State saveTmpFile(File tmpFile, String rootPath, String path, boolean isImage) {
        State state = null;
        Watermark watermark = null;
        String targetFilePath = path;
        if (isImage) {
            ServletRequestAttributes servletRequestAttributes =
                    (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            watermark = (Watermark) servletRequestAttributes.getRequest().getSession().getAttribute("watermark");
            if (watermark.isEndble()) targetFilePath += ".tmp";
        }
        File targetFile = new File(targetFilePath);
        if (targetFile.canWrite()) {
            return new BaseState(false, AppInfo.PERMISSION_DENIED);
        }
        try {
            FileUtils.moveFile(tmpFile, targetFile);
            if (isImage && watermark.isEndble())
                waterHunter.imageWaterMark(path, rootPath + "/resource/image/watermark.png", watermark.getPosition(), watermark.getMarginX(), watermark.getMarginY(), watermark.getTransparence());
        } catch (Exception e) {
            return new BaseState(false, AppInfo.IO_ERROR);
        }
        state = new BaseState(true);
        state.putInfo("size", targetFile.length());
        state.putInfo("title", targetFile.getName());
        return state;
    }

    private static State valid(File file) {
        File parentPath = file.getParentFile();
        if ((!parentPath.exists()) && (!parentPath.mkdirs())) {
            return new BaseState(false, AppInfo.FAILED_CREATE_FILE);
        }
        if (!parentPath.canWrite()) {
            return new BaseState(false, AppInfo.PERMISSION_DENIED);
        }
        return new BaseState(true);
    }
}
